﻿using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System.Reflection;

namespace B.S.Meeting.ReadAPI.Filter
{
    /// <summary>
    /// Excel通过泛型及反射的导出
    /// </summary>
    public static class ExcelExporter
    {
        /// <summary>
        /// 将泛型列表数据导出到Excel文件
        /// </summary>
        /// <typeparam name="T">要导出数据的数据类型</typeparam>
        /// <param name="list">要导出的数据列表</param>
        /// <param name="sheetName">工作表名称</param>
        /// <returns>包含Excel文件内容的内存流</returns>
        public static byte[] ExportToExcel<T>(IList<T> list,string sheetName="Entity") where T : class
        {
            //创建一个Excel工作簿
            IWorkbook wb = new XSSFWorkbook();
            //创建一个工作表
            ISheet sheet = wb.CreateSheet(sheetName);

            //获取泛型类型的元数据信息
            Type type = typeof(T);
            //获取该类型的所有公共属性信息
            PropertyInfo[] propertyInfos = type.GetProperties();

            //创建标题行（从第0行开始）
            IRow hrow =sheet.CreateRow(0);
            // 遍历所有属性，为标题行创建单元格并设置标题文本
            for (int i = 0; i < propertyInfos.Length; i++) 
            {
                //创建标题单元格
                ICell cell = hrow.CreateCell(i);
                //设置标题单元格的值为属性名称
                cell.SetCellValue(propertyInfos[i].Name);
                //设置标题单元格的样式（可选）
                ICellStyle style = wb.CreateCellStyle();
                style.Alignment = HorizontalAlignment.Center; //水平居中
                style.VerticalAlignment = VerticalAlignment.Center; //垂直居中
                style.FillForegroundColor = IndexedColors.LightBlue.Index; //设置背景色
                style.FillPattern = FillPattern.SolidForeground; //填充模式
                IFont font = wb.CreateFont();//创建字体
                font.IsBold = true; //设置字体为粗体
                style.SetFont(font); //应用字体到样式
                cell.CellStyle = style; //应用样式到单元格
            }

            // 遍历数据集合，填充工作表的数据行
            for (int rowIndex = 0; rowIndex < list.Count; rowIndex++) 
            {
                //创建数据行（从第1行开始）
                IRow drow= sheet.CreateRow(rowIndex + 1);
                //获取当前行的数据对象
                T item = list[rowIndex];
                // 遍历所有属性，为当前行的每个单元格设置对应属性的值
                for (int cellIndex = 0; cellIndex < propertyInfos.Length; cellIndex++) 
                {
                    //获取当前列属性的元数据
                    PropertyInfo prop = propertyInfos[cellIndex];
                    //获取当前列属性的值（处理null值）
                    object value = prop.GetValue(item, null)??DBNull.Value;
                    //创建单元格
                    ICell cell = drow.CreateCell(cellIndex);
                    //根据属性类型设置单元格的值
                    SetCellFormat(cell, value);
                }
            }

            //调整列宽以适应内容
            for (int i = 0; i < propertyInfos.Length; i++)
            {
               sheet.AutoSizeColumn(i); //自动调整列宽
            }

            //保存文件
            using (MemoryStream ms = new MemoryStream())
            {
                wb.Write(ms);
                return ms.ToArray();
            }
        }


        private static void SetCellFormat(ICell cell, object value)
        {
            if (value == null)
            {
                cell.SetCellType(CellType.Blank);//设置单元格类型为空
                return;
            }
            if(value is DBNull)
            {
                cell.SetCellValue(string.Empty);//设置单元格值为空字符串
            }
            else if(value is DateTime)
            {
                cell.SetCellValue((DateTime)value);//设置单元格值为日期时间
                ICellStyle style = cell.Sheet.Workbook.CreateCellStyle();//创建单元格样式
                style.DataFormat = cell.Sheet.Workbook.CreateDataFormat().GetFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
                cell.CellStyle = style;//应用样式到单元格
            }
            else if(value is bool)
            {
                cell.SetCellValue((bool)value);
            }
            else if(value is byte[])
            {
                cell.SetCellValue(Convert.ToBase64String((byte[])value));//将字节数组转换为Base64字符串
            }
            else if(value is double)
            {
                cell.SetCellValue((double)value);//设置单元格值为双精度浮点数
            }
            else
            {
                cell.SetCellValue(value.ToString());//将其他类型转换为字符串
            }
        }
    }
}
